package org.anyline.data.jdbc.adapter.init;

import org.anyline.data.param.ConfigStore;
import org.anyline.data.run.Run;
import org.anyline.data.run.SimpleRun;
import org.anyline.data.runtime.DataRuntime;
import org.anyline.metadata.ACTION;
import org.anyline.metadata.Column;
import org.anyline.metadata.Constraint;
import org.anyline.metadata.Table;
import org.anyline.util.BasicUtil;
import org.anyline.util.BeanUtil;
import org.anyline.util.ConfigTable;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

public abstract class PostgresGenusAdapter extends SQLAdapter {

    /**
     * 查询表上的列
     * @param table 表
     * @param metadata 是否根据metadata(true:1=0,false:查询系统表)
     * @return sql
     */
    @Override
    public List<Run> buildQueryColumnRun(DataRuntime runtime, Table table, boolean metadata) throws Exception{
        List<Run> runs = new ArrayList<>();
        String catalog = null;
        String schema = null;
        String name = null;
        if(null != table){
            name = table.getName();
            catalog = table.getCatalog();
            schema = table.getSchema();
        }
        Run run = new SimpleRun(runtime);
        runs.add(run);
        StringBuilder builder = run.getBuilder();
        if(metadata){
            builder.append("SELECT * FROM ");
            name(runtime, builder, table);
            builder.append(" WHERE 1=0");
        }else{
            builder.append("SELECT M.* ,pg_catalog.format_type ( FA.ATTTYPID, FA.ATTTYPMOD ) AS FULL_TYPE,FD.DESCRIPTION AS COLUMN_COMMENT \n");
            builder.append("FROM INFORMATION_SCHEMA.COLUMNS M\n");
            builder.append("LEFT JOIN PG_CLASS FC ON FC.RELNAME = M.TABLE_NAME\n");
            builder.append("LEFT JOIN PG_ATTRIBUTE AS FA ON FA.ATTNAME = M.COLUMN_NAME AND FA.ATTRELID = FC.OID\n");
            builder.append("LEFT JOIN PG_DESCRIPTION FD ON FD.OBJOID = FC.OID AND FD.OBJSUBID = M.ORDINAL_POSITION\n");
            builder.append("WHERE 1 = 1\n");
            if(BasicUtil.isNotEmpty(catalog)){
                builder.append(" AND M.TABLE_CATALOG = '").append(catalog).append("'");
            }
            if(BasicUtil.isNotEmpty(schema)){
                builder.append(" AND M.TABLE_SCHEMA = '").append(schema).append("'");
            }
            if(BasicUtil.isNotEmpty(name)) {
                builder.append(" AND M.TABLE_NAME = '").append(name).append("'");
            }
            builder.append(" ORDER BY M.TABLE_NAME");
        }
        return runs;
    }

    /**
     * 批量插入时
     * @param configs ConfigStore
     * @param columns columns
     * @return String
     */
    @Override
    public String insertFoot(ConfigStore configs, LinkedHashMap<String, Column> columns){
        StringBuilder builder = new StringBuilder();
        Boolean override = null;
        if(null != configs){
            override = configs.override();
        }
        if(null != override){
            builder.append(" ON CONFLICT");
            Constraint constraint = configs.overrideByConstraint();
            if(null != constraint){
                //ON CONFLICT ON CONSTRAINT 约束
                builder.append(" ON CONSTRAINT ").append(constraint.getName());
            }else {
                List<String> bys = configs.overrideByColumns();
                if (null == bys) {
                    bys = configs.getPrimaryKeys();
                }
                if (null == bys) {
                    bys = new ArrayList<>();
                }
                if (bys.isEmpty()) {
                    bys.add(ConfigTable.DEFAULT_PRIMARY_KEY);
                }
                //ON CONFLICT ( id )
                builder.append("(").append(BeanUtil.concat(bys)).append(")");
            }
            if(override){
                builder.append(" DO UPDATE SET ");
                boolean first = true;
                for(Column column:columns.values()){
                    if(!first){
                        builder.append(",");
                    }
                    first = false;
                    builder.append(column.getName()).append(" = EXCLUDED.").append(column.getName());
                }
            }else{
                builder.append(" DO NOTHING");
            }

        }
        return builder.toString();
    }
    /**
     * 数据类型
     * @param builder builder
     * @param column 列
     * @return builder
     */
    @Override
    public StringBuilder type(DataRuntime runtime, StringBuilder builder, Column column){
        String type = column.getTypeName();
        if(null == type){
            type ="";
        }
        type = type.toLowerCase();
        //创建并自增时 或 非自增改自增时 用serial 其他情况用int
        boolean serial = false;
        if(ACTION.DDL.COLUMN_ADD == column.getAction() && column.isAutoIncrement() == 1){
            serial = true;
        }else {
            Column update = column.getUpdate();
            if(null != update && update.isAutoIncrement() !=1 && column.isAutoIncrement() == 1){
                serial = true;
            }
        }
        if(serial){
            if ("int4".equals(type) || "int".equals(type) || "integer".equals(type)) {
                column.setType("SERIAL4");
            } else if ("int8".equals(type) || "long".equals(type) || "bigint".equals(type)) {
                column.setType("SERIAL8");
            } else if ("int2".equals(type) || "smallint".equals(type) || "short".equals(type)) {
                //9.2.0
                column.setType("SERIAL2");
            }else{
                column.setType("SERIAL8");
            }
        }else if(type.contains("int") || type.contains("long") || type.contains("serial") || type.contains("short")){
            if ("serial4".equals(type) || "int".equals(type) || "integer".equals(type)) {
                column.setType("int4");
            } else if ("serial8".equals(type) || "long".equals(type) || "bigint".equals(type)) {
                column.setType("int8");
            } else if ("serial2".equals(type) || "smallint".equals(type) || "short".equals(type)) {
                column.setType("int2");
            }else{
                column.setType("int8");
            }
        }
        return super.type(runtime, builder, column);
    }
}
